import {IpcChannel, IpcRendererInvoke, IpcRendererOn} from "@main/ipc";
import {onUnmounted} from "vue";

const ipcRenderer = window.ipcRenderer;	//此处已经是子进程（渲染进程）中了，不再直接使用nodejs的api来require调用，而是用electron的进程通信方式，由主进程去调用，子进程用windows.*来通信
type VoidParametersIpcRendererInvokeKey = {
	[K in keyof IpcRendererInvoke]: Parameters<IpcRendererInvoke[K]>[0] extends void ? K : never
}[keyof IpcRendererInvoke]
type NotVoidParametersIpcRendererInvokeKey = Exclude<keyof IpcRendererInvoke, VoidParametersIpcRendererInvokeKey>

/**
 * 将channel暴露给需要的页面
 */
export {IpcChannel};

/**
 * 从渲染进程向主进程发送指令
 * 用法： invoke("start-wsserver")  或者  invoke(IpcChannel.StartWsServer)
 * 进程名称
 */
export function invoke<T extends VoidParametersIpcRendererInvokeKey>(channel: T): ReturnType<IpcRendererInvoke[T]>;
export function invoke<T extends NotVoidParametersIpcRendererInvokeKey>(channel: T, args: Parameters<IpcRendererInvoke[T]>[0]): ReturnType<IpcRendererInvoke[T]>;

export function invoke<T extends keyof IpcRendererInvoke>(channel: T, args?: Parameters<IpcRendererInvoke[T]>[0]) {
	return ipcRenderer.invoke(channel, args) as ReturnType<IpcRendererInvoke[T]>
}

/**
 * 监听从主进程发送出来的指令
 */
/**
 * ipcRendererOn Vue setup中使用
 *
 * @export
 * @template T
 * @param {T} channel
 * @param {IpcRendererOn[T]} callback
 */
export function vueListen<T extends keyof IpcRendererOn>(channel: T, callback: IpcRendererOn[T]) {

	ipcRenderer.on(channel, callback)
	onUnmounted(() => {
		ipcRenderer.removeListener(channel, callback);
	})
}

/**
 * ipcRendererOn
 *
 * @export
 * @template T
 * @param {T} channel
 * @param {IpcRendererOn[T]} callback
 * @return {() => void} 副作用清理函数
 */
export function listen<T extends keyof IpcRendererOn>(channel: T, callback: IpcRendererOn[T]): () => void {
	ipcRenderer.on(channel, callback)
	return () => {
		ipcRenderer.removeListener(channel, callback);
	}
}
